/**
 * 
 */
package info.niwota.webapp.acl;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.security.MessageDigest;
import java.security.SecureRandom;

import android.text.TextUtils;

/**
 * 
 * @author qiangli
 * 
 */
public class CryptoHelper {
	//
	private final static String secret = random();
	
	private final static int LEN = 16;
	
	private final static char[] ALPHABET = { 'A', 'B', 'C', 'D', 'E',
			'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R',
			'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e',
			'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r',
			's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4',
			'5', '6', '7', '8', '9', '+', '/' };
	private final static char CR = '\r';
	private final static char LF = '\n';
	private final static char PAD = '=';

	private static void base64Encode(InputStream is, OutputStream os)
			throws Exception {
		int i, j, count;
		byte[] s = new byte[76 * 3 / 4];
		byte[] d = new byte[76 + 2];

		while ((count = is.read(s)) != -1) {
			for (i = 0, j = 0; i < count; i += 3) {
				switch ((count - i) > 3 ? 3 : (count - i)) {
				case 1:
					d[j++] = (byte) ALPHABET[(s[i] >>> 2) & 0x3F];
					d[j++] = (byte) ALPHABET[((s[i] << 4) & 0x30)];
					d[j++] = (byte) PAD;
					d[j++] = (byte) PAD;
					break;
				case 2:
					d[j++] = (byte) ALPHABET[(s[i] >>> 2) & 0x3F];
					d[j++] = (byte) ALPHABET[((s[i] << 4) & 0x30)
							| ((s[i + 1] >>> 4) & 0x0F)];
					d[j++] = (byte) ALPHABET[((s[i + 1] << 2) & 0x3C)];
					d[j++] = (byte) PAD;
					break;
				case 3:
					d[j++] = (byte) ALPHABET[(s[i] >>> 2) & 0x3F];
					d[j++] = (byte) ALPHABET[((s[i] << 4) & 0x30)
							| ((s[i + 1] >>> 4) & 0x0F)];
					d[j++] = (byte) ALPHABET[((s[i + 1] << 2) & 0x3C)
							| ((s[i + 2] >>> 6) & 0x03)];
					d[j++] = (byte) ALPHABET[s[i + 2] & 0x3F];
				}
			}
			d[j++] = (byte) CR;
			d[j++] = (byte) LF;
			os.write(d, 0, j);
		}
	}
	
	public static String hash(String uri, String label, String group, String user) throws Exception {
			String s = digest(secret + "|"+ uri + "|" + label+"|"+group+"|"+user);
			return URLEncoder.encode(s);
		
	}
	
	public static String hash(String p, String label, int group, String user, boolean encode) throws Exception {
			String s = digest(secret + "|"+ p + "|" + label+"|"+group+"|"+user);
			return (encode? URLEncoder.encode(s) : s);
	}

	public static String digest(String str) throws Exception {
		if (TextUtils.isEmpty(str)) {
			return null;
		}
		final String algorithm = "SHA-1";
		MessageDigest md = MessageDigest.getInstance(algorithm);
		md.reset();
		md.update(str.getBytes());
		byte[] b = md.digest();
		//
		return encodeBytes(b);
	}

	private static String encodeBytes(byte[] b) throws Exception {
		ByteArrayInputStream is = new ByteArrayInputStream(b);
		ByteArrayOutputStream os = new ByteArrayOutputStream();
		base64Encode(is, os);
		return os.toString();
	}

	public static byte[] random(int len) throws Exception {
		SecureRandom rand = SecureRandom.getInstance("SHA1PRNG");
		byte[] b = new byte[len];
		rand.nextBytes(b);
		return b;
	}

	private static String random() {
		try {
			byte[] b = random(LEN);
			String enc = encodeBytes(b);
			return enc;
		} catch (Exception e) {
		}
		return System.currentTimeMillis()+"";
	}
}
